package cn.com.w.bootdemo.util;

import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

import java.util.Iterator;

/**
 * post process：后置处理
 * BeanPostProcessor都是Spring初始化bean时对外暴露的扩展点
 *   Spring IoC容器允许BeanFactoryPostProcessor在容器实例化任何bean之前读取bean的定义(配置元数据)，
 *   并可以修改它。同时可以定义多个BeanFactoryPostProcessor，
 *   通过设置'order'属性来确定各个BeanFactoryPostProcessor执行顺序。
 *
 *   注册一个BeanFactoryPostProcessor实例需要定义一个Java类来实现BeanFactoryPostProcessor接口，
 *   并重写该接口的postProcessorBeanFactory方法。通过beanFactory可以获取bean的定义信息，
 *   并可以修改bean的定义信息。这点是和BeanPostProcessor最大区别
 *
 */
@Component
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor, Ordered {

    @Override
    public int getOrder() {
        return 0;
    }

    /**
     * ConfigurableListableBeanFactory 其实就是DefaultListableBeanDefinition对象
     * 定义
     *      * 1.在标准初始化之后修改应用程序上下文的内部bean工厂。
     *      * 2.所有bean定义都已加载，但还没有实例化bean。这允许覆盖或添加属性，甚至可以在快速初始化bean。
     *      *   * 本方法在Bean对象实例化之前执行，
     *      * 	 * 通过beanFactory可以获取bean的定义信息，
     *      * 	 * 并可以修改bean的定义信息。这点是和BeanPostProcessor最大区别
     * @param beanFactory
     * @throws BeansException
     */

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println(">>>>>>>>>>>>>>>>调用自定义CoustomBeanfactoryPostProcess<<<<<<<<<<<<<<<<<<");
        // 获取了所有的bean名称列表
        String[] names = beanFactory.getBeanDefinitionNames();
        for (String beanName : names) {
            if ("user".equals(beanName)) {
                BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
                String factoryBeanName = beanDefinition.getFactoryBeanName();
                String beanClassName = beanDefinition.getBeanClassName();
                String description = beanDefinition.getDescription();
                String initMethodName = beanDefinition.getInitMethodName();
                String scope = beanDefinition.getScope();
                MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();

                // MutablePropertyValues如果设置了相关属性，可以修改，如果没有设置则可以添加相关属性信息
               /* if(propertyValues.contains("name")){
                    propertyValues.addPropertyValue("name", "赵四");
                    System.out.println("修改了属性信息");
                } else {
                    propertyValues.addPropertyValue("addr", "北京");
                    System.out.println("添加了属性信息");
                }*/

            }
        }
    }
}